<template>
  <div class="image-editor-container">
    <!-- 顶部文件上传和图片展示区域 -->
    <div class="upload-header">
      <div class="upload-actions">
        <el-upload class="file-upload" action="#" :auto-upload="false" :on-change="handleFileChange"
          :show-file-list="false" multiple>
          <el-button type="primary">
            <el-icon>
              <Upload />
            </el-icon>
            选择文件
          </el-button>
        </el-upload>
        <span class="upload-tip" v-if="imageList.length > 0">已上传 {{ imageList.length }} 张图片</span>
      </div>
    </div>

    <!-- 顶部图片预览区域 -->
    <div class="image-preview-list" v-if="imageList.length > 0">
      <div v-for="(image, index) in imageList" :key="index" class="image-preview-item"
        :class="{ active: currentImageIndex === index }" @click="selectImage(index)">
        <img :src="image.url" alt="预览图" />
        <!-- 删除按钮 -->
        <div class="delete-button" @click.stop="deleteImage(index)">
          <el-icon>
            <Delete />
          </el-icon>
        </div>
      </div>
    </div>
    <el-empty v-else description="请上传图片" />

    <!-- 主要内容区域 -->
    <div class="main-content" v-if="imageList.length > 0">
      <!-- 左侧图片编辑区域 -->
      <div class="editor-section">
        <div class="editor-toolbar">
          <!-- 缩放和平移工具 -->
          <div class="zoom-tools">
            <el-tooltip content="放大" placement="top">
              <el-button type="primary" :icon="ZoomIn" @click="zoomIn"></el-button>
            </el-tooltip>
            <el-tooltip content="缩小" placement="top">
              <el-button type="primary" :icon="ZoomOut" @click="zoomOut"></el-button>
            </el-tooltip>
            <el-tooltip content="重置视图" placement="top">
              <el-button type="primary" :icon="Refresh" @click="resetView"></el-button>
            </el-tooltip>
            <span class="zoom-level">{{ Math.round(zoomLevel * 100) }}%</span>
          </div>

          <el-divider direction="vertical" />

          <!-- 截图工具 -->
          <el-button-group>
            <el-tooltip content="矩形截图" placement="top">
              <el-button type="primary" :icon="Crop" @click="startRectCropping"
                :class="{ active: isRectCropping }">矩形截图</el-button>
            </el-tooltip>
            <el-tooltip content="钢笔截图" placement="top">
              <el-button type="primary" :icon="Edit" @click="startPenCropping"
                :class="{ active: isPenCropping }">钢笔截图</el-button>
            </el-tooltip>
            <el-tooltip content="清除" placement="top">
              <el-button type="primary" :icon="Delete" @click="clearCanvas">清除</el-button>
            </el-tooltip>
          </el-button-group>

          <div class="drawing-options" v-if="isPenCropping">
            <el-color-picker v-model="drawingColor" size="small" />
            <el-slider v-model="lineWidth" :min="1" :max="10" :step="1" style="width: 100px" />
          </div>
        </div>

        <div class="canvas-container" ref="canvasContainer" @wheel="handleWheel" @mousedown="handleCanvasMouseDown"
          @mousemove="handleCanvasMouseMove" @mouseup="handleCanvasMouseUp" @mouseleave="handleCanvasMouseUp"
          @touchstart="handleCanvasTouchStart" @touchmove="handleCanvasTouchMove" @touchend="handleCanvasTouchEnd">
          <!-- 原始图片画布 -->
          <canvas ref="imageCanvas"></canvas>

          <!-- 绘图层画布 -->
          <canvas ref="drawingCanvas" class="drawing-canvas"></canvas>

          <!-- 矩形截图覆盖层 -->
          <div class="crop-overlay" v-if="isRectCropping">
            <div class="crop-selection" :style="{
              left: `${cropSelection.x}px`,
              top: `${cropSelection.y}px`,
              width: `${cropSelection.width}px`,
              height: `${cropSelection.height}px`,
            }" @mousedown.stop="handleCropMouseDown" @touchstart.stop="handleCropTouchStart">
              <div class="resize-handle top-left" @mousedown.stop="handleResizeMouseDown('topLeft')"></div>
              <div class="resize-handle top-right" @mousedown.stop="handleResizeMouseDown('topRight')"></div>
              <div class="resize-handle bottom-left" @mousedown.stop="handleResizeMouseDown('bottomLeft')"></div>
              <div class="resize-handle bottom-right" @mousedown.stop="handleResizeMouseDown('bottomRight')"></div>
            </div>
          </div>
        </div>

        <div class="editor-actions">
          <el-button type="success" @click="applyCurrentCrop" :disabled="!canApplyCrop">确认截图</el-button>
          <el-button @click="cancelCrop">取消</el-button>
        </div>
      </div>

      <!-- 右侧卡片区域 -->
      <div class="result-section">
        <el-card class="result-card">
          <template #header>
            <div class="card-header">
              <span>截图结果</span>
              <el-select v-model="resultType" placeholder="选择类型" class="result-type-select">
                <el-option label="卡片" value="card"></el-option>
                <el-option label="图片上传" value="picture-upload"></el-option>
              </el-select>
            </div>
          </template>

          <div class="result-content">
            <div class="result-image-container" v-if="croppedImageUrl">
              <img :src="croppedImageUrl" alt="截图结果" class="result-image" />
            </div>
            <div class="empty-result" v-else>
              <el-icon class="empty-icon">
                <Picture />
              </el-icon>
              <span>请先截取图片</span>
            </div>

            <div class="result-actions">
              <el-button type="primary" size="small" @click="previewCroppedImage"
                :disabled="!croppedImageUrl">预览</el-button>
              <el-button type="success" size="small" @click="recognizeCroppedImage"
                :disabled="!croppedImageUrl">识别</el-button>
              <el-button type="info" size="small" @click="downloadCroppedImage"
                :disabled="!croppedImageUrl">下载</el-button>
            </div>
          </div>
        </el-card>
      </div>
    </div>

    <!-- 底部操作区域 -->
    <div class="bottom-actions" v-if="imageList.length > 0">
      <el-button type="primary" @click="recognizeAll">全部识别</el-button>
      <el-button type="success" @click="downloadAll">打包下载</el-button>
    </div>

    <!-- 预览对话框 -->
    <el-dialog v-model="previewVisible" title="图片预览" width="50%">
      <img :src="croppedImageUrl" v-if="croppedImageUrl" style="width: 100%" />
    </el-dialog>

    <!-- 识别结果对话框 -->
    <el-dialog v-model="recognizeResultVisible" title="识别结果" width="50%">
      <div class="recognize-result">
        <el-result icon="success" title="识别完成" sub-title="已成功识别图片内容">
          <template #extra>
            <div class="result-content">
              <p>识别结果将在这里显示</p>
              <el-skeleton :rows="3" animated v-if="isRecognizing" />
              <div v-else class="mock-result">
                <p><strong>文件类型:</strong> 图片</p>
                <p><strong>尺寸:</strong> {{ mockImageSize }}</p>
                <p><strong>内容描述:</strong> {{ mockRecognizeResult }}</p>
              </div>
            </div>
          </template>
        </el-result>
      </div>
    </el-dialog>

    <!-- 删除确认对话框 -->
    <el-dialog v-model="deleteConfirmVisible" title="确认删除" width="30%">
      <span>确定要删除这张图片吗？</span>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="deleteConfirmVisible = false">取消</el-button>
          <el-button type="danger" @click="confirmDelete">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, computed, watch, nextTick } from "vue";
import {
  Upload,
  Picture,
  Crop,
  Edit,
  Delete,
  ZoomIn,
  ZoomOut,
  Refresh,
} from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";

interface ImageItem {
  name: string;
  url: string;
  file: File;
}

interface Point {
  x: number;
  y: number;
}

// 状态变量
const imageList = ref<ImageItem[]>([]);
const currentImageIndex = ref(-1);
const currentImage = computed(() =>
  currentImageIndex.value >= 0 ? imageList.value[currentImageIndex.value] : null
);
const resultType = ref("card");
const croppedImageUrl = ref("");
const previewVisible = ref(false);
const recognizeResultVisible = ref(false);
const isRecognizing = ref(false);
const mockImageSize = ref("640 x 480 px");
const mockRecognizeResult = ref("这是一张包含文字和图表的截图");

// 当前中心点
const currentCenterX = ref(0);
const currentCenterY = ref(0);

// 删除确认对话框
const deleteConfirmVisible = ref(false);
const imageToDeleteIndex = ref(-1);

// 画布相关
const imageCanvas = ref<HTMLCanvasElement | null>(null);
const drawingCanvas = ref<HTMLCanvasElement | null>(null);
const canvasContainer = ref<HTMLDivElement | null>(null);
const imageContext = ref<CanvasRenderingContext2D | null>(null);
const drawingContext = ref<CanvasRenderingContext2D | null>(null);
const originalImage = ref<HTMLImageElement | null>(null);

// 缩放和平移状态
const zoomLevel = ref(1);
const panOffset = ref({ x: 0, y: 0 });
const isPanning = ref(false);
const panStart = ref({ x: 0, y: 0 });
const MIN_ZOOM = 0.1;
const MAX_ZOOM = 5;
const ZOOM_STEP = 0.1;

// 截图状态
const isRectCropping = ref(false);
const isPenCropping = ref(false);
const isDrawingActive = ref(false);
const drawingColor = ref("#FF0000");
const lineWidth = ref(3);
const lastPoint = ref<Point>({ x: 0, y: 0 });
const penPath = ref<Point[]>([]);
const hasCompletedPath = ref(false);

// 矩形裁剪状态
const cropSelection = ref({
  x: 50,
  y: 50,
  width: 200,
  height: 150,
  dragging: false,
  resizing: false,
  resizeHandle: "",
  startX: 0,
  startY: 0,
});

// 计算属性
const canApplyCrop = computed(() => {
  return (
    (isRectCropping.value &&
      cropSelection.value.width > 10 &&
      cropSelection.value.height > 10) ||
    (isPenCropping.value && hasCompletedPath.value)
  );
});

// 文件上传处理
const handleFileChange = (file: any) => {
  const reader = new FileReader();
  reader.onload = (e) => {
    if (e.target?.result) {
      const newImage: ImageItem = {
        name: file.name,
        url: e.target.result as string,
        file: file.raw,
      };
      imageList.value.push(newImage);

      // 自动选择新上传的图片
      currentImageIndex.value = imageList.value.length - 1;

      // 重置缩放和平移
      resetView();

      // 确保DOM更新后再初始化画布
      nextTick(() => {
        console.log("初始化画布");
        initCanvas();
        loadImageToCanvas();
      });

      ElMessage.success("图片上传成功");
    }
  };
  reader.readAsDataURL(file.raw);
};

// 删除图片
const deleteImage = (index: number) => {
  imageToDeleteIndex.value = index;
  deleteConfirmVisible.value = true;
};

// 确认删除图片
const confirmDelete = () => {
  if (
    imageToDeleteIndex.value >= 0 &&
    imageToDeleteIndex.value < imageList.value.length
  ) {
    // 删除图片
    imageList.value.splice(imageToDeleteIndex.value, 1);

    // 关闭确认对话框
    deleteConfirmVisible.value = false;

    // 处理当前选中的图片
    if (imageList.value.length === 0) {
      // 如果没有图片了，重置当前索引
      currentImageIndex.value = -1;
      croppedImageUrl.value = "";
    } else if (currentImageIndex.value === imageToDeleteIndex.value) {
      // 如果删除的是当前选中的图片，选择另一张
      currentImageIndex.value = Math.min(
        imageToDeleteIndex.value,
        imageList.value.length - 1
      );

      // 重新加载画布
      nextTick(() => {
        resetCanvas();
        resetView();
        loadImageToCanvas();
      });
    } else if (currentImageIndex.value > imageToDeleteIndex.value) {
      // 如果删除的图片在当前选中图片之前，需要调整索引
      currentImageIndex.value--;
    }

    ElMessage.success("图片已删除");
  }
};

// 选择图片
const selectImage = (index: number) => {
  currentImageIndex.value = index;
  resetCanvas();
  resetView();

  // 确保DOM更新后再加载图片
  nextTick(() => {
    console.log("加载图片到画布");
    loadImageToCanvas();
  });
};

// 画布初始化
const initCanvas = () => {
  console.log("初始化画布函数被调用");
  const canvas = imageCanvas.value;
  const drawCanvas = drawingCanvas.value;
  if (!canvas || !drawCanvas) {
    console.error("Canvas元素未找到");
    return;
  }

  if (!canvasContainer.value) {
    console.error("Canvas容器未找到");
    return;
  }

  imageContext.value = canvas.getContext("2d");
  // 设置绘图层的透明度
  drawingContext.value = drawCanvas.getContext("2d", { alpha: true });

  if (!imageContext.value || !drawingContext.value) {
    console.error("无法获取Canvas上下文");
    return;
  }

  // 设置初始画布大小
  const containerWidth = canvasContainer.value.clientWidth;
  console.log("容器宽度:", containerWidth);
  canvas.width = containerWidth;
  canvas.height = 500; // 默认高度

  drawCanvas.width = containerWidth;
  drawCanvas.height = 500;

  console.log("画布尺寸设置为:", canvas.width, "x", canvas.height);
};

// 加载图片到画布
const loadImageToCanvas = () => {
  console.log("加载图片到画布函数被调用");
  if (!currentImage.value) {
    console.error("当前没有选中的图片");
    return;
  }

  if (!imageCanvas.value || !drawingCanvas.value) {
    console.error("Canvas元素未找到");
    return;
  }

  console.log("当前图片URL:", currentImage.value.url);

  const img = new Image();
  img.crossOrigin = "anonymous"; // 避免CORS问题

  img.onload = () => {
    console.log("图片加载成功, 尺寸:", img.width, "x", img.height);
    originalImage.value = img;

    // 调整画布大小以适应图片
    if (imageCanvas.value && drawingCanvas.value && canvasContainer.value) {
      const containerWidth = canvasContainer.value.clientWidth;
      const scale = containerWidth / img.width;
      const scaledHeight = img.height * scale;

      console.log("调整画布尺寸为:", containerWidth, "x", scaledHeight);

      imageCanvas.value.width = containerWidth;
      imageCanvas.value.height = scaledHeight;
      drawingCanvas.value.width = containerWidth;
      drawingCanvas.value.height = scaledHeight;

      // 绘制图片
      drawImageWithTransform();

      // 重置裁剪选择框
      cropSelection.value = {
        x: 50,
        y: 50,
        width: Math.min(200, containerWidth - 100),
        height: Math.min(150, scaledHeight - 100),
        dragging: false,
        resizing: false,
        resizeHandle: "",
        startX: 0,
        startY: 0,
      };
    }
  };

  img.onerror = (error) => {
    console.error("图片加载失败:", error);
    ElMessage.error("图片加载失败");
  };

  img.src = currentImage.value.url;
};

// 使用变换绘制图片
const drawImageWithTransform = () => {
  if (!imageContext.value || !imageCanvas.value || !originalImage.value) return;

  const canvas = imageCanvas.value;
  const ctx = imageContext.value;
  const img = originalImage.value;

  // 清除画布
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // 保存当前状态
  ctx.save();

  // 应用平移和缩放
  ctx.translate(panOffset.value.x, panOffset.value.y);
  ctx.scale(zoomLevel.value, zoomLevel.value);

  // 计算居中位置
  const scaledWidth = img.width;
  const scaledHeight = img.height;
  const centerX = (canvas.width / zoomLevel.value - scaledWidth) / 2;
  const centerY = (canvas.height / zoomLevel.value - scaledHeight) / 2;

  // 保存中心点坐标
  currentCenterX.value = centerX;
  currentCenterY.value = centerY;
  // 绘制图片
  ctx.drawImage(img, centerX, centerY, scaledWidth, scaledHeight);

  // 恢复状态
  ctx.restore();

  // 如果有绘图路径，重新绘制
  if (isPenCropping.value && penPath.value.length > 0 && drawingContext.value) {
    const drawCtx = drawingContext.value;
    drawCtx.clearRect(0, 0, canvas.width, canvas.height);

    drawCtx.strokeStyle = drawingColor.value;
    drawCtx.lineWidth = lineWidth.value;
    drawCtx.lineCap = "round";
    drawCtx.lineJoin = "round";

    drawCtx.beginPath();
    drawCtx.moveTo(penPath.value[0].x, penPath.value[0].y);

    for (let i = 1; i < penPath.value.length; i++) {
      drawCtx.lineTo(penPath.value[i].x, penPath.value[i].y);
    }

    if (hasCompletedPath.value) {
      drawCtx.closePath();
    }

    drawCtx.stroke();
  }
};

// 缩放和平移功能
const zoomIn = () => {
  if (zoomLevel.value < MAX_ZOOM) {
    zoomLevel.value += ZOOM_STEP;
    drawImageWithTransform();
  }
};

const zoomOut = () => {
  if (zoomLevel.value > MIN_ZOOM) {
    zoomLevel.value -= ZOOM_STEP;
    drawImageWithTransform();
  }
};

const resetView = () => {
  zoomLevel.value = 1;
  panOffset.value = { x: 0, y: 0 };
  drawImageWithTransform();
};

const handleWheel = (e: WheelEvent) => {
  e.preventDefault();

  // 确定鼠标位置
  const rect = imageCanvas.value?.getBoundingClientRect();
  if (!rect) return;

  const mouseX = e.clientX - rect.left;
  const mouseY = e.clientY - rect.top;

  // 根据滚轮方向缩放
  if (e.deltaY < 0) {
    // 向上滚动，放大
    if (zoomLevel.value < MAX_ZOOM) {
      zoomLevel.value += ZOOM_STEP;
    }
  } else {
    // 向下滚动，缩小
    if (zoomLevel.value > MIN_ZOOM) {
      zoomLevel.value -= ZOOM_STEP;
    }
  }

  drawImageWithTransform();
};

// 重置画布
const resetCanvas = () => {
  isRectCropping.value = false;
  isPenCropping.value = false;
  isDrawingActive.value = false;
  hasCompletedPath.value = false;
  penPath.value = [];

  // 清除绘图层
  if (drawingContext.value && drawingCanvas.value) {
    drawingContext.value.clearRect(
      0,
      0,
      drawingCanvas.value.width,
      drawingCanvas.value.height
    );
  }
};

// 清除画布
const clearCanvas = () => {
  if (
    !imageContext.value ||
    !imageCanvas.value ||
    !drawingContext.value ||
    !drawingCanvas.value
  )
    return;

  // 重新加载原始图片
  drawImageWithTransform();

  // 重置状态
  hasCompletedPath.value = false;
  penPath.value = [];

  // 清除绘图层
  if (drawingContext.value) {
    drawingContext.value.clearRect(
      0,
      0,
      drawingCanvas.value.width,
      drawingCanvas.value.height
    );
  }

  ElMessage.success("已清除所有编辑");
};

// 开始矩形截图模式
const startRectCropping = () => {
  isRectCropping.value = true;
  isPenCropping.value = false;
  isPanning.value = false;
  hasCompletedPath.value = false;
  penPath.value = [];

  // 清除绘图层
  if (drawingContext.value && drawingCanvas.value) {
    drawingContext.value.clearRect(
      0,
      0,
      drawingCanvas.value.width,
      drawingCanvas.value.height
    );
  }
};

// 开始钢笔截图模式
const startPenCropping = () => {
  isPenCropping.value = true;
  isRectCropping.value = false;
  isPanning.value = false;
  hasCompletedPath.value = false;
  penPath.value = [];

  // 清除绘图层
  if (drawingContext.value && drawingCanvas.value) {
    drawingContext.value.clearRect(
      0,
      0,
      drawingCanvas.value.width,
      drawingCanvas.value.height
    );
  }
};

// 取消截图
const cancelCrop = () => {
  isRectCropping.value = false;
  isPenCropping.value = false;
  hasCompletedPath.value = false;
  penPath.value = [];

  // 清除绘图层
  if (drawingContext.value && drawingCanvas.value) {
    drawingContext.value.clearRect(
      0,
      0,
      drawingCanvas.value.width,
      drawingCanvas.value.height
    );
  }
};

// 应用当前截图
const applyCurrentCrop = () => {
  if (isRectCropping.value) {
    applyRectCrop();
  } else if (isPenCropping.value && hasCompletedPath.value) {
    applyPenCrop();
  } else {
    ElMessage.warning("请先完成截图操作");
  }
};

// 应用矩形截图
const applyRectCrop = () => {
  if (!originalImage.value) return;
  // 转换为原始坐标
  const originalX =
    (cropSelection.value.x - panOffset.value.x) / zoomLevel.value -
    currentCenterX.value;
  const originalY =
    (cropSelection.value.y - panOffset.value.y) / zoomLevel.value -
    currentCenterY.value;
  const originalWidth = cropSelection.value.width / zoomLevel.value;
  const originalHeight = cropSelection.value.height / zoomLevel.value;

  // 边界检查
  const imgWidth = originalImage.value.width;
  const imgHeight = originalImage.value.height;
  const x = Math.max(0, Math.min(originalX, imgWidth));
  const y = Math.max(0, Math.min(originalY, imgHeight));
  const width = Math.min(originalWidth, imgWidth - x);
  const height = Math.min(originalHeight, imgHeight - y);

  // 创建临时画布存储裁剪的图像
  const tempCanvas = document.createElement("canvas");
  tempCanvas.width = width;
  tempCanvas.height = height;
  const tempContext = tempCanvas.getContext("2d");

  if (tempContext) {
    // 填充背景
    tempContext.fillStyle = "#FFFFFF";
    tempContext.fillRect(0, 0, width, height);

    // 从原始画布复制选定区域
    tempContext.drawImage(
      originalImage.value,
      x,
      y,
      width,
      height,
      0,
      0,
      width,
      height
    );

    // 将裁剪后的图像转换为数据URL
    croppedImageUrl.value = tempCanvas.toDataURL("image/png");

    ElMessage.success("矩形截图已完成");
    isRectCropping.value = false;

    // 更新尺寸
    mockImageSize.value = `${width} x ${height} px`;
  }
};

// 钢笔截图
const applyPenCrop = () => {
  if (
    !originalImage.value ||
    !drawingContext.value ||
    penPath.value.length < 3
  ) {
    ElMessage.warning("请先完成闭合路径绘制");
    return;
  }

  // 转换所有路径点到原始图像坐标并进行平滑处理
  const originalPath = smoothPath(
    penPath.value.map((point) => ({
      x: (point.x - panOffset.value.x) / zoomLevel.value - currentCenterX.value,
      y: (point.y - panOffset.value.y) / zoomLevel.value - currentCenterY.value,
    })),
    0.5 // 平滑系数
  );

  // 路径优化：使用贝塞尔曲线平滑
  const optimizedPath = chaikinSmooth(originalPath, 2); // 进行两次平滑迭代

  // 计算路径的边界框（使用优化后的路径）
  const { minX, minY, maxX, maxY } = optimizedPath.reduce(
    (acc, point) => ({
      minX: Math.min(acc.minX, point.x),
      minY: Math.min(acc.minY, point.y),
      maxX: Math.max(acc.maxX, point.x),
      maxY: Math.max(acc.maxY, point.y),
    }),
    {
      minX: Infinity,
      minY: Infinity,
      maxX: -Infinity,
      maxY: -Infinity,
    }
  );

  const newWidth = maxX - minX;
  const newHeight = maxY - minY;

  if (newWidth <= 0 || newHeight <= 0) {
    ElMessage.warning("无效的截图区域");
    return;
  }

  // 创建高分辨率临时画布（2倍尺寸用于抗锯齿）
  const scaleFactor = 2;
  const tempCanvas = document.createElement("canvas");
  tempCanvas.width = newWidth * scaleFactor;
  tempCanvas.height = newHeight * scaleFactor;
  const tempContext = tempCanvas.getContext("2d", { alpha: true });

  if (!tempContext) return;

  // 启用抗锯齿
  tempContext.imageSmoothingEnabled = true;
  tempContext.imageSmoothingQuality = "high";

  // 创建剪切路径（使用优化后的路径）
  tempContext.beginPath();
  tempContext.moveTo(
    (optimizedPath[0].x - minX) * scaleFactor,
    (optimizedPath[0].y - minY) * scaleFactor
  );
  optimizedPath.slice(1).forEach((point) => {
    tempContext.lineTo(
      (point.x - minX) * scaleFactor,
      (point.y - minY) * scaleFactor
    );
  });
  tempContext.closePath();
  tempContext.clip();

  // 绘制原图到剪切区域（高质量缩放）
  tempContext.drawImage(
    originalImage.value,
    minX,
    minY,
    newWidth,
    newHeight,
    0,
    0,
    newWidth * scaleFactor,
    newHeight * scaleFactor
  );

  // 创建最终输出画布（降采样到原始尺寸）
  const outputCanvas = document.createElement("canvas");
  outputCanvas.width = newWidth;
  outputCanvas.height = newHeight;
  const outputContext = outputCanvas.getContext("2d");

  if (outputContext) {
    outputContext.imageSmoothingEnabled = true;
    outputContext.imageSmoothingQuality = "high";
    outputContext.drawImage(
      tempCanvas,
      0,
      0,
      tempCanvas.width,
      tempCanvas.height,
      0,
      0,
      newWidth,
      newHeight
    );
  }

  // 生成最终结果
  croppedImageUrl.value = outputCanvas.toDataURL("image/png");
  mockImageSize.value = `${newWidth} x ${newHeight} px`;

  // 重置状态
  isPenCropping.value = false;
  hasCompletedPath.value = false;
  penPath.value = [];
  drawingContext.value.clearRect(
    0,
    0,
    drawingCanvas.value!.width,
    drawingCanvas.value!.height
  );

  ElMessage.success("钢笔截图已完成");
};
// 路径平滑算法（Chaikin角切割）
const chaikinSmooth = (path: Point[], iterations: number): Point[] => {
  let currentPath = [...path];
  for (let i = 0; i < iterations; i++) {
    const newPath: Point[] = [];
    for (let j = 0; j < currentPath.length; j++) {
      const p1 = currentPath[j];
      const p2 = currentPath[(j + 1) % currentPath.length];
      newPath.push({
        x: p1.x * 0.75 + p2.x * 0.25,
        y: p1.y * 0.75 + p2.y * 0.25,
      });
      newPath.push({
        x: p1.x * 0.25 + p2.x * 0.75,
        y: p1.y * 0.25 + p2.y * 0.75,
      });
    }
    currentPath = newPath;
  }
  return currentPath;
};

// 二次贝塞尔曲线平滑
const smoothPath = (path: Point[], tension: number): Point[] => {
  if (path.length < 3) return path;

  const smoothed: Point[] = [];
  smoothed.push(path[0]);

  for (let i = 1; i < path.length - 1; i++) {
    const p0 = path[i - 1];
    const p1 = path[i];
    const p2 = path[i + 1];

    const cp1x = p1.x + (p2.x - p0.x) * tension;
    const cp1y = p1.y + (p2.y - p0.y) * tension;

    for (let t = 0; t <= 1; t += 0.2) {
      const x =
        (1 - t) * (1 - t) * p1.x + 2 * (1 - t) * t * cp1x + t * t * p2.x;
      const y =
        (1 - t) * (1 - t) * p1.y + 2 * (1 - t) * t * cp1y + t * t * p2.y;
      smoothed.push({ x, y });
    }
  }

  smoothed.push(path[path.length - 1]);
  return smoothed;
};
// 获取鼠标在画布上的坐标
const getCanvasCoordinates = (e: MouseEvent): Point => {
  const rect = imageCanvas.value?.getBoundingClientRect();
  if (!rect) return { x: 0, y: 0 };

  return {
    x: e.clientX - rect.left,
    y: e.clientY - rect.top,
  };
};

// 获取触摸在画布上的坐标
const getTouchCoordinates = (e: TouchEvent): Point => {
  const rect = imageCanvas.value?.getBoundingClientRect();
  if (!rect || !e.touches[0]) return { x: 0, y: 0 };

  return {
    x: e.touches[0].clientX - rect.left,
    y: e.touches[0].clientY - rect.top,
  };
};

// 画布鼠标事件处理
const handleCanvasMouseDown = (e: MouseEvent) => {
  if (isPenCropping.value) {
    isDrawingActive.value = true;
    const point = getCanvasCoordinates(e);

    // 开始新路径
    if (penPath.value.length === 0) {
      penPath.value.push(point);

      if (drawingContext.value) {
        drawingContext.value.strokeStyle = drawingColor.value;
        drawingContext.value.lineWidth = lineWidth.value;
        drawingContext.value.lineCap = "round";
        drawingContext.value.lineJoin = "round";
        drawingContext.value.beginPath();
        drawingContext.value.moveTo(point.x, point.y);
      }
    }

    lastPoint.value = point;
  } else if (!isRectCropping.value) {
    // 启动平移模式
    isPanning.value = true;
    panStart.value = getCanvasCoordinates(e);
  }
};

const handleCanvasMouseMove = (e: MouseEvent) => {
  if (isPenCropping.value && isDrawingActive.value && drawingContext.value) {
    const point = getCanvasCoordinates(e);

    // 添加点到路径
    penPath.value.push(point);

    // 绘制线段
    drawingContext.value.lineTo(point.x, point.y);
    drawingContext.value.stroke();

    lastPoint.value = point;
  } else if (isPanning.value && !isRectCropping.value && !isPenCropping.value) {
    // 平移图片
    const currentPoint = getCanvasCoordinates(e);
    const deltaX = currentPoint.x - panStart.value.x;
    const deltaY = currentPoint.y - panStart.value.y;

    panOffset.value.x += deltaX;
    panOffset.value.y += deltaY;
    panStart.value = currentPoint;

    drawImageWithTransform();
  }
};

const handleCanvasMouseUp = () => {
  if (
    isPenCropping.value &&
    isDrawingActive.value &&
    penPath.value.length > 2
  ) {
    isDrawingActive.value = false;

    // 闭合路径
    if (drawingContext.value && penPath.value.length > 0) {
      const firstPoint = penPath.value[0];
      drawingContext.value.lineTo(firstPoint.x, firstPoint.y);
      drawingContext.value.stroke();

      // 标记路径已完成
      hasCompletedPath.value = true;
    }
  } else {
    isDrawingActive.value = false;
  }

  // 结束平移
  isPanning.value = false;
};

// 触摸事件处理
const handleCanvasTouchStart = (e: TouchEvent) => {
  e.preventDefault();
  if (isPenCropping.value) {
    isDrawingActive.value = true;
    const point = getTouchCoordinates(e);

    // 开始新路径
    if (penPath.value.length === 0) {
      penPath.value.push(point);

      if (drawingContext.value) {
        drawingContext.value.strokeStyle = drawingColor.value;
        drawingContext.value.lineWidth = lineWidth.value;
        drawingContext.value.lineCap = "round";
        drawingContext.value.lineJoin = "round";
        drawingContext.value.beginPath();
        drawingContext.value.moveTo(point.x, point.y);
      }
    }

    lastPoint.value = point;
  } else if (!isRectCropping.value) {
    // 启动平移模式
    isPanning.value = true;
    panStart.value = getTouchCoordinates(e);
  }
};

const handleCanvasTouchMove = (e: TouchEvent) => {
  e.preventDefault();
  if (isPenCropping.value && isDrawingActive.value && drawingContext.value) {
    const point = getTouchCoordinates(e);

    // 添加点到路径
    penPath.value.push(point);

    // 绘制线段
    drawingContext.value.lineTo(point.x, point.y);
    drawingContext.value.stroke();

    lastPoint.value = point;
  } else if (isPanning.value && !isRectCropping.value && !isPenCropping.value) {
    // 平移图片
    const currentPoint = getTouchCoordinates(e);
    const deltaX = currentPoint.x - panStart.value.x;
    const deltaY = currentPoint.y - panStart.value.y;

    panOffset.value.x += deltaX;
    panOffset.value.y += deltaY;
    panStart.value = currentPoint;

    drawImageWithTransform();
  }
};

const handleCanvasTouchEnd = (e: TouchEvent) => {
  e.preventDefault();
  if (
    isPenCropping.value &&
    isDrawingActive.value &&
    penPath.value.length > 2
  ) {
    isDrawingActive.value = false;

    // 闭合路径
    if (drawingContext.value && penPath.value.length > 0) {
      const firstPoint = penPath.value[0];
      drawingContext.value.lineTo(firstPoint.x, firstPoint.y);
      drawingContext.value.stroke();

      // 标记路径已完成
      hasCompletedPath.value = true;
    }
  } else {
    isDrawingActive.value = false;
  }

  // 结束平移
  isPanning.value = false;
};

// 矩形裁剪区域拖动和调整大小
const handleCropMouseDown = (e: MouseEvent) => {
  cropSelection.value.dragging = true;
  cropSelection.value.startX = e.clientX - cropSelection.value.x;
  cropSelection.value.startY = e.clientY - cropSelection.value.y;

  document.addEventListener("mousemove", handleCropMouseMove);
  document.addEventListener("mouseup", handleCropMouseUp);
};

const handleCropTouchStart = (e: TouchEvent) => {
  if (!e.touches[0]) return;

  cropSelection.value.dragging = true;
  cropSelection.value.startX = e.touches[0].clientX - cropSelection.value.x;
  cropSelection.value.startY = e.touches[0].clientY - cropSelection.value.y;

  document.addEventListener("touchmove", handleCropTouchMove);
  document.addEventListener("touchend", handleCropTouchEnd);
};

const handleResizeMouseDown = (handle: string) => {
  cropSelection.value.resizing = true;
  cropSelection.value.resizeHandle = handle;

  document.addEventListener("mousemove", handleResizeMouseMove);
  document.addEventListener("mouseup", handleResizeMouseUp);
};

const handleCropMouseMove = (e: MouseEvent) => {
  if (cropSelection.value.dragging && imageCanvas.value) {
    const rect = imageCanvas.value.getBoundingClientRect();
    let newX = e.clientX - cropSelection.value.startX;
    let newY = e.clientY - cropSelection.value.startY;

    // 限制在画布范围内
    newX = Math.max(0, Math.min(newX, rect.width - cropSelection.value.width));
    newY = Math.max(
      0,
      Math.min(newY, rect.height - cropSelection.value.height)
    );

    cropSelection.value.x = newX;
    cropSelection.value.y = newY;
  }
};

const handleCropTouchMove = (e: TouchEvent) => {
  if (cropSelection.value.dragging && imageCanvas.value && e.touches[0]) {
    const rect = imageCanvas.value.getBoundingClientRect();
    let newX = e.touches[0].clientX - cropSelection.value.startX;
    let newY = e.touches[0].clientY - cropSelection.value.startY;

    // 限制在画布范围内
    newX = Math.max(0, Math.min(newX, rect.width - cropSelection.value.width));
    newY = Math.max(
      0,
      Math.min(newY, rect.height - cropSelection.value.height)
    );

    cropSelection.value.x = newX;
    cropSelection.value.y = newY;
  }
};

const handleResizeMouseMove = (e: MouseEvent) => {
  if (cropSelection.value.resizing && imageCanvas.value) {
    const rect = imageCanvas.value.getBoundingClientRect();
    const handle = cropSelection.value.resizeHandle;

    if (handle === "topLeft") {
      const newWidth =
        cropSelection.value.width +
        (cropSelection.value.x - (e.clientX - rect.left));
      const newHeight =
        cropSelection.value.height +
        (cropSelection.value.y - (e.clientY - rect.top));

      if (newWidth > 10 && newHeight > 10) {
        cropSelection.value.width = newWidth;
        cropSelection.value.height = newHeight;
        cropSelection.value.x = e.clientX - rect.left;
        cropSelection.value.y = e.clientY - rect.top;
      }
    } else if (handle === "topRight") {
      const newWidth = e.clientX - rect.left - cropSelection.value.x;
      const newHeight =
        cropSelection.value.height +
        (cropSelection.value.y - (e.clientY - rect.top));

      if (newWidth > 10 && newHeight > 10) {
        cropSelection.value.width = newWidth;
        cropSelection.value.height = newHeight;
        cropSelection.value.y = e.clientY - rect.top;
      }
    } else if (handle === "bottomLeft") {
      const newWidth =
        cropSelection.value.width +
        (cropSelection.value.x - (e.clientX - rect.left));
      const newHeight = e.clientY - rect.top - cropSelection.value.y;

      if (newWidth > 10 && newHeight > 10) {
        cropSelection.value.width = newWidth;
        cropSelection.value.height = newHeight;
        cropSelection.value.x = e.clientX - rect.left;
      }
    } else if (handle === "bottomRight") {
      const newWidth = e.clientX - rect.left - cropSelection.value.x;
      const newHeight = e.clientY - rect.top - cropSelection.value.y;

      if (newWidth > 10 && newHeight > 10) {
        cropSelection.value.width = newWidth;
        cropSelection.value.height = newHeight;
      }
    }
  }
};

const handleResizeTouchMove = (e: TouchEvent) => {
  if (cropSelection.value.resizing && imageCanvas.value && e.touches[0]) {
    const rect = imageCanvas.value.getBoundingClientRect();
    const handle = cropSelection.value.resizeHandle;
    const clientX = e.touches[0].clientX;
    const clientY = e.touches[0].clientY;

    if (handle === "topLeft") {
      const newWidth =
        cropSelection.value.width +
        (cropSelection.value.x - (clientX - rect.left));
      const newHeight =
        cropSelection.value.height +
        (cropSelection.value.y - (clientY - rect.top));

      if (newWidth > 10 && newHeight > 10) {
        cropSelection.value.width = newWidth;
        cropSelection.value.height = newHeight;
        cropSelection.value.x = clientX - rect.left;
        cropSelection.value.y = clientY - rect.top;
      }
    } else if (handle === "topRight") {
      const newWidth = clientX - rect.left - cropSelection.value.x;
      const newHeight =
        cropSelection.value.height +
        (cropSelection.value.y - (clientY - rect.top));

      if (newWidth > 10 && newHeight > 10) {
        cropSelection.value.width = newWidth;
        cropSelection.value.height = newHeight;
        cropSelection.value.y = clientY - rect.top;
      }
    } else if (handle === "bottomLeft") {
      const newWidth =
        cropSelection.value.width +
        (cropSelection.value.x - (clientX - rect.left));
      const newHeight = clientY - rect.top - cropSelection.value.y;

      if (newWidth > 10 && newHeight > 10) {
        cropSelection.value.width = newWidth;
        cropSelection.value.height = newHeight;
        cropSelection.value.x = clientX - rect.left;
      }
    } else if (handle === "bottomRight") {
      const newWidth = clientX - rect.left - cropSelection.value.x;
      const newHeight = clientY - rect.top - cropSelection.value.y;

      if (newWidth > 10 && newHeight > 10) {
        cropSelection.value.width = newWidth;
        cropSelection.value.height = newHeight;
      }
    }
  }
};

const handleCropMouseUp = () => {
  cropSelection.value.dragging = false;
  document.removeEventListener("mousemove", handleCropMouseMove);
  document.removeEventListener("mouseup", handleCropMouseUp);
};

const handleCropTouchEnd = () => {
  cropSelection.value.dragging = false;
  document.removeEventListener("touchmove", handleCropTouchMove);
  document.removeEventListener("touchend", handleCropTouchEnd);
};

const handleResizeMouseUp = () => {
  cropSelection.value.resizing = false;
  document.removeEventListener("mousemove", handleResizeMouseMove);
  document.removeEventListener("mouseup", handleResizeMouseUp);
};

const handleResizeTouchUp = () => {
  cropSelection.value.resizing = false;
  document.removeEventListener("touchmove", handleResizeTouchMove);
  document.removeEventListener("touchend", handleResizeTouchUp);
};

// 截图结果操作
const previewCroppedImage = () => {
  if (!croppedImageUrl.value) {
    ElMessage.warning("请先截取图片");
    return;
  }
  previewVisible.value = true;
};

const recognizeCroppedImage = () => {
  if (!croppedImageUrl.value) {
    ElMessage.warning("请先截取图片");
    return;
  }

  recognizeResultVisible.value = true;
  isRecognizing.value = true;

  // 模拟识别过程
  setTimeout(() => {
    isRecognizing.value = false;
    // 随机生成一些识别结果
    const results = [
      "这是一张包含文字和图表的截图",
      "这是一张包含表格数据的截图",
      "这是一张包含图形和标注的截图",
      "这是一张包含代码片段的截图",
    ];
    mockRecognizeResult.value =
      results[Math.floor(Math.random() * results.length)];
  }, 1500);
};

const downloadCroppedImage = () => {
  if (!croppedImageUrl.value) {
    ElMessage.warning("请先截取图片");
    return;
  }

  // 创建一个临时链接并触发下载
  const a = document.createElement("a");
  a.href = croppedImageUrl.value;
  a.download = "cropped-image.png";
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);

  ElMessage.success("截图下载成功");
};

// 批量操作
const recognizeAll = () => {
  ElMessage.success("所有图片识别任务已开始，请稍候...");
  // 实际项目中这里应该调用后端API进行批量识别
};

const downloadAll = () => {
  ElMessage.success("图片打包下载已开始");
  // 实际项目中这里应该调用后端API进行打包下载
};

// 监听图片变化，重新加载画布
watch(currentImageIndex, () => {
  resetCanvas();
  resetView();

  // 确保DOM更新后再加载图片
  nextTick(() => {
    console.log("监听到图片变化，重新加载画布");
    loadImageToCanvas();
  });
});

// 组件挂载时初始化画布
onMounted(() => {
  console.log("组件已挂载");
  // 初始化时不需要立即初始化画布，等待图片上传后再初始化
});
</script>

<style lang="scss" scoped>
.image-editor-container {
  max-width: 1200px;
  margin: 20px auto;
  padding: 20px;
  font-family: "PingFang SC", "Microsoft YaHei", sans-serif;

  .upload-header {
    margin-bottom: 20px;

    .upload-actions {
      display: flex;
      align-items: center;
      margin-bottom: 15px;

      .upload-tip {
        margin-left: 15px;
        color: #606266;
      }
    }
  }

  .image-preview-list {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    padding: 10px 0;
    margin-bottom: 15px;

    .image-preview-item {
      position: relative;
      width: 100px;
      height: 70px;
      border-radius: 4px;
      overflow: hidden;
      cursor: pointer;
      border: 2px solid transparent;
      transition: all 0.3s;

      &:hover {
        transform: translateY(-3px);
        box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);

        .delete-button {
          opacity: 1;
        }
      }

      &.active {
        border-color: #409eff;
      }

      img {
        width: 100%;
        height: 100%;
        object-fit: cover;
      }

      .delete-button {
        position: absolute;
        top: 0;
        right: 0;
        width: 24px;
        height: 24px;
        background-color: rgba(255, 0, 0, 0.7);
        color: white;
        display: flex;
        align-items: center;
        justify-content: center;
        opacity: 0;
        transition: opacity 0.3s;
        cursor: pointer;

        &:hover {
          background-color: rgba(255, 0, 0, 0.9);
        }
      }
    }
  }

  .main-content {
    display: flex;
    gap: 20px;
    margin-bottom: 20px;

    @media (max-width: 768px) {
      flex-direction: column;
    }

    .editor-section {
      flex: 1;
      background-color: #f9f9f9;
      border-radius: 8px;
      padding: 15px;
      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);

      .editor-toolbar {
        display: flex;
        align-items: center;
        margin-bottom: 15px;
        gap: 15px;
        flex-wrap: wrap;

        .zoom-tools {
          display: flex;
          align-items: center;
          gap: 5px;

          .zoom-level {
            min-width: 50px;
            text-align: center;
            font-weight: bold;
          }
        }

        .active {
          background-color: #67c23a;
          border-color: #67c23a;
        }

        .drawing-options {
          display: flex;
          align-items: center;
          gap: 10px;
        }
      }

      .canvas-container {
        position: relative;
        width: 100%;
        margin-bottom: 15px;
        border: 1px solid #dcdfe6;
        border-radius: 4px;
        overflow: hidden;
        min-height: 300px;
        /* 确保Canvas容器有最小高度 */
        cursor: grab;

        &:active {
          cursor: grabbing;
        }

        canvas {
          display: block;
          background-color: #fff;
        }

        .drawing-canvas {
          position: absolute;
          top: 0;
          left: 0;
          pointer-events: none;
          background-color: transparent;
          /* 确保绘图层是透明的 */
        }

        .crop-overlay {
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background-color: rgba(0, 0, 0, 0.5);

          .crop-selection {
            position: absolute;
            border: 2px dashed #fff;
            background-color: rgba(255, 255, 255, 0.1);
            cursor: move;

            .resize-handle {
              position: absolute;
              width: 10px;
              height: 10px;
              background-color: #fff;
              border: 1px solid #409eff;

              &.top-left {
                top: -5px;
                left: -5px;
                cursor: nw-resize;
              }

              &.top-right {
                top: -5px;
                right: -5px;
                cursor: ne-resize;
              }

              &.bottom-left {
                bottom: -5px;
                left: -5px;
                cursor: sw-resize;
              }

              &.bottom-right {
                bottom: -5px;
                right: -5px;
                cursor: se-resize;
              }
            }
          }
        }
      }

      .editor-actions {
        display: flex;
        justify-content: center;
        gap: 10px;
      }
    }

    .result-section {
      width: 350px;

      @media (max-width: 768px) {
        width: 100%;
      }

      .result-card {
        height: 100%;

        .card-header {
          display: flex;
          justify-content: space-between;
          align-items: center;

          .result-type-select {
            width: 150px;
          }
        }

        .result-content {
          display: flex;
          flex-direction: column;
          gap: 15px;

          .result-image-container {
            width: 100%;
            height: 200px;
            border: 1px solid #ebeef5;
            border-radius: 4px;
            overflow: hidden;

            .result-image {
              width: 100%;
              height: 100%;
              object-fit: contain;
            }
          }

          .empty-result {
            width: 100%;
            height: 200px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            border: 1px dashed #dcdfe6;
            border-radius: 4px;
            color: #909399;

            .empty-icon {
              font-size: 48px;
              margin-bottom: 10px;
            }
          }

          .result-actions {
            display: flex;
            justify-content: space-between;
          }
        }
      }
    }
  }

  .bottom-actions {
    display: flex;
    gap: 10px;
  }

  .recognize-result {
    .result-content {
      background-color: #f8f8f8;
      padding: 15px;
      border-radius: 6px;
      margin-top: 15px;

      .mock-result {
        line-height: 1.6;
      }
    }
  }
}
</style>